package com.report.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.report.dto.CompanyTreeStructureDto;
import com.report.dto.Response;
import com.report.entity.CompanyTreeStructure;
import com.report.enumeration.MergeTypeEnum;
import com.report.enumeration.ReportTypeEnum;
import com.report.repository.CompanyTreeStructureRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CompanyTreeStructureService {

    @Autowired
    private CompanyTreeStructureRepository companyTreeStructureRepository;

    public List<CompanyTreeStructureDto> getCompanyTree(String auditCompanyUscc) {
        List<CompanyTreeStructure> companyTreeStructures = companyTreeStructureRepository.findByAuditCompanyUscc(auditCompanyUscc);
        if (CollectionUtil.isEmpty(companyTreeStructures)) {
            return new ArrayList<>();
        }
        //return buildTree(Convert.toList(CompanyTreeStructureDto.class, companyTreeStructures));

        return buildTreexx(Convert.toList(CompanyTreeStructureDto.class, companyTreeStructures));
    }

    public Response addCompanyTree(CompanyTreeStructure companyTreeStructure) {
        Response response = new Response();
        response.setStatus("success");
        for (MergeTypeEnum value : MergeTypeEnum.values()) {
            // 单户表只显示本部汇总
            if (ReportTypeEnum.SINGLE.getCode() == companyTreeStructure.getReportType() && value != MergeTypeEnum.HQ_SUM) {
                continue;
            }
            CompanyTreeStructure convert = new CompanyTreeStructure();
            BeanUtils.copyProperties(companyTreeStructure, convert);
            convert.setMergeType(value.getCode());
            convert.setCurrentCompany(convert.getCurrentCompany() + "(" + value.getDesc() + ")");
            CompanyTreeStructure save = companyTreeStructureRepository.save(convert);
        }
        return response;
    }


    private List<CompanyTreeStructureDto> buildTree(List<CompanyTreeStructureDto> dtos) {

        // 按currentCompanyUscc分组节点
        Map<String, List<CompanyTreeStructureDto>> nodes = dtos.stream().collect(Collectors.groupingBy(CompanyTreeStructureDto::getCurrentCompanyUscc));

        List<CompanyTreeStructureDto> companyTreeStructureDtoList = new ArrayList<>();
        //先将当前企业信用代码相同的节点 构建父子关系
        for (Map.Entry<String, List<CompanyTreeStructureDto>> entry : nodes.entrySet()) {
            List<CompanyTreeStructureDto> companyTreeStructureDtos = entry.getValue();
            CompanyTreeStructureDto companyTreeStructureDto = companyTreeStructureDtos.stream().filter(node -> node.getMergeType() == 0).findFirst().orElse(null);
            //单户表没有合并节点
            if (companyTreeStructureDto == null && ReportTypeEnum.SINGLE.getCode().equals(companyTreeStructureDtos.get(0).getReportType())) {
                companyTreeStructureDtoList.add(companyTreeStructureDtos.get(0));
                continue;
            }
            if (companyTreeStructureDto == null) {
                continue;
            }
            //合并表有本部汇总和差额
            companyTreeStructureDto.setChildren(companyTreeStructureDtos.stream().filter(node -> node.getMergeType() != 0).collect(Collectors.toList()));
            companyTreeStructureDtoList.add(companyTreeStructureDto);
        }
        return buildTree(companyTreeStructureDtoList);






        /*// 按currentCompanyUscc分组节点
        Map<String, List<CompanyTreeStructureDto>> nodesByUscc = dtos.stream()
                .filter(dto -> dto.getCurrentCompanyUscc() != null && !dto.getCurrentCompanyUscc().isEmpty())
                .collect(Collectors.groupingBy(CompanyTreeStructureDto::getCurrentCompanyUscc));

        // 收集所有根节点
        List<CompanyTreeStructureDto> rootNodes = new ArrayList<>();

        // 为每个节点组确定父子关系
        for (Map.Entry<String, List<CompanyTreeStructureDto>> entry : nodesByUscc.entrySet()) {
            String currentUscc = entry.getKey();
            List<CompanyTreeStructureDto> nodeGroup = entry.getValue();

            if (!nodeGroup.isEmpty()) {
                CompanyTreeStructureDto firstNode = nodeGroup.get(0);
                String parentUscc = firstNode.getHigherCompanyUscc();

                // 检查是否为自引用
                if (parentUscc != null && parentUscc.equals(currentUscc)) {
                    // 自引用，作为根节点处理
                    rootNodes.addAll(nodeGroup);
                }
                // 检查是否有有效的父节点
                else if (parentUscc != null && !parentUscc.isEmpty() && nodesByUscc.containsKey(parentUscc)) {
                    // 有父节点，将当前节点组添加到所有父节点的子节点列表中
                    List<CompanyTreeStructureDto> parentGroup = nodesByUscc.get(parentUscc);
                    for (CompanyTreeStructureDto parentNode : parentGroup) {
                        // 确保children列表不为null
                        if (parentNode.getChildren() == null) {
                            parentNode.setChildren(new ArrayList<>());
                        }
                        parentNode.getChildren().addAll(nodeGroup);
                    }
                } else {
                    // 没有父节点或父节点不存在，作为根节点处理
                    rootNodes.addAll(nodeGroup);
                }
            }
        }

        return rootNodes;*/
    }


    public Response deleteCompanyTree(CompanyTreeStructure companyTreeStructure) {
        List<Integer> ids = new ArrayList<>();
        List<CompanyTreeStructureDto> companyTree = getCompanyTree(companyTreeStructure.getAuditCompanyUscc());
        companyTree.forEach(companyTreeStructureDto -> {
            processDeleteId(ids, companyTreeStructureDto, false, companyTreeStructure.getId());
        });
        companyTreeStructureRepository.deleteAllById(ids);
        return Response.success();
    }

    public void processDeleteId(List<Integer> ids, CompanyTreeStructureDto companyTree, boolean isRoot, Integer id) {
        if (Objects.equals(id, companyTree.getId())) {
            isRoot = true;
            ids.add(companyTree.getId());
        }
        for (CompanyTreeStructureDto companyTreeStructureDto : companyTree.getChildren()) {
            if (isRoot) {
                ids.add(companyTreeStructureDto.getId());
            }
            processDeleteId(ids, companyTreeStructureDto, isRoot, id);
        }
    }


    /**
     * 构建公司树形结构
     *
     * @param nodes 原始节点列表
     * @return 树形结构的根节点列表
     */
    public static List<CompanyTreeStructureDto> buildTreexx(List<CompanyTreeStructureDto> nodes) {
        if (nodes == null || nodes.isEmpty()) {
            return new ArrayList<>();
        }

        // 初始化所有节点的子节点列表
        nodes.forEach(node -> {
            if (node.getChildren() == null) {
                node.setChildren(new ArrayList<>());
            }
        });

        // 用于记录已作为子节点的节点，避免重复父节点引用
        Set<CompanyTreeStructureDto> usedAsChild = new HashSet<>();

        // 规则1: 按currentCompanyUscc分组，处理相同uscc的节点
        Map<String, List<CompanyTreeStructureDto>> groupByUscc = nodes.stream()
                .collect(Collectors.groupingBy(CompanyTreeStructureDto::getCurrentCompanyUscc));

        processRule1(groupByUscc, usedAsChild);

        // 规则2: 处理不同uscc的节点父子关系
        processRule2(nodes, usedAsChild, groupByUscc);

        // 返回根节点（未被用作子节点的节点）
        return nodes.stream()
                .filter(node -> !usedAsChild.contains(node))
                .collect(Collectors.toList());
    }

    /**
     * 处理规则1: 相同currentCompanyUscc的节点，mergeType!=0的作为mergeType=0的子节点
     */
    private static void processRule1(Map<String, List<CompanyTreeStructureDto>> groupByUscc, Set<CompanyTreeStructureDto> usedAsChild) {
        for (List<CompanyTreeStructureDto> group : groupByUscc.values()) {
            if (group.size() > 1) { // 只有多个节点才需要处理
                // 查找mergeType=0的候选父节点
                List<CompanyTreeStructureDto> parentCandidates = group.stream()
                        .filter(node -> node.getMergeType() != null && node.getMergeType() == 0)
                        .collect(Collectors.toList());

                // 查找mergeType!=0的子节点
                List<CompanyTreeStructureDto> childCandidates = group.stream()
                        .filter(node -> node.getMergeType() != null && node.getMergeType() != 0)
                        .collect(Collectors.toList());

                if (!parentCandidates.isEmpty() && !childCandidates.isEmpty()) {
                    // 取第一个mergeType=0的节点作为父节点
                    CompanyTreeStructureDto parent = parentCandidates.get(0);

                    for (CompanyTreeStructureDto child : childCandidates) {
                        parent.getChildren().add(child);
                        usedAsChild.add(child);
                    }
                }
            }
        }
    }

    /**
     * 处理规则2: currentCompanyUscc不相同的节点，作为higherCompanyUscc匹配节点的子节点
     */
    private static void processRule2(List<CompanyTreeStructureDto> nodes, Set<CompanyTreeStructureDto> usedAsChild,
                                     Map<String, List<CompanyTreeStructureDto>> groupByUscc) {
        for (CompanyTreeStructureDto node : nodes) {
            // 如果节点已作为子节点，跳过
            if (usedAsChild.contains(node)) {
                continue;
            }

            String higherUscc = node.getHigherCompanyUscc();
            if (higherUscc != null && !higherUscc.trim().isEmpty()) {
                // 查找higherUscc对应的父节点
                List<CompanyTreeStructureDto> possibleParents = groupByUscc.get(higherUscc);

                if (possibleParents != null && !possibleParents.isEmpty()) {
                    // 取第一个有效的父节点（未被用作子节点，且不是当前节点的后代）
                    Optional<CompanyTreeStructureDto> validParent = possibleParents.stream()
                            .filter(parent -> !usedAsChild.contains(parent) && !isDescendant(node, parent))
                            .findFirst();

                    if (validParent.isPresent()) {
                        CompanyTreeStructureDto parent = validParent.get();
                        parent.getChildren().add(node);
                        usedAsChild.add(node);
                    }
                }
            }
        }
    }

    /**
     * 检查节点是否是另一个节点的后代（防止循环引用）
     */
    private static boolean isDescendant(CompanyTreeStructureDto node, CompanyTreeStructureDto potentialAncestor) {
        if (potentialAncestor == null || node == null) {
            return false;
        }

        // 简单的循环引用检查
        if (potentialAncestor.equals(node)) {
            return true;
        }

        // 检查所有子节点
        for (CompanyTreeStructureDto child : potentialAncestor.getChildren()) {
            if (isDescendant(node, child)) {
                return true;
            }
        }

        return false;
    }


}
